package labox.innovation.gameserver.network.clientpackets;

import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import labox.innovation.config.Config;
import labox.innovation.db.core.L2DatabaseFactory;
import labox.innovation.gameserver.Announcements;
import labox.innovation.gameserver.Engine;
import labox.innovation.gameserver.GmListTable;
import labox.innovation.gameserver.datatables.AdminCommandAccessRights;
import labox.innovation.gameserver.datatables.CharNameTable;
import labox.innovation.gameserver.instancemanager.CoupleManager;
import labox.innovation.gameserver.instancemanager.InstanceManager;
import labox.innovation.gameserver.model.ConsignmentManager;
import labox.innovation.gameserver.model.FuzeWorld;
import labox.innovation.gameserver.model.L2ItemInstance;
import labox.innovation.gameserver.model.L2PartyManager;
import labox.innovation.gameserver.model.L2ShortCut;
import labox.innovation.gameserver.model.Scene;
import labox.innovation.gameserver.model.FuzeSkillCoolDown.TimeStamp;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;
import labox.innovation.gameserver.model.entity.Couple;
import labox.innovation.gameserver.model.quest.QuestState;
import labox.innovation.gameserver.network.SystemMessageId;
import labox.innovation.gameserver.network.L2GameClient.GameClientState;
import labox.innovation.gameserver.network.serverpackets.ActionFailed;
import labox.innovation.gameserver.network.serverpackets.MagicSkillUse;
import labox.innovation.gameserver.network.serverpackets.PkModelPacket;
import labox.innovation.gameserver.network.serverpackets.ReponseChatSwitches;
import labox.innovation.gameserver.network.serverpackets.ShortCutRegister;
import labox.innovation.gameserver.network.serverpackets.SystemMessage;
import labox.innovation.gameserver.network.serverpackets.UserBaseInfo;
import labox.innovation.util.crypt.Base64;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 客户端请求进入游戏世界
 * <p>
 */
public final class EnterWorld extends L2GameClientPacket {

	private static final String _C__03_ENTERWORLD = "[C] 03 EnterWorld";

	private static final Logger _log = LoggerFactory.getLogger(EnterWorld.class.getName());

	private int _charSlot;

	@Override
	protected void readImpl() {
		_charSlot = readInt();
	}

	@Override
	protected void runImpl() {
		// The L2PcInstance must be created here, so that it can be attached to
		// the L2GameClient
		if (_log.isDebugEnabled()) {
			_log.debug("selected slot:" + _charSlot);
		}

		FuzePcInstance activeChar;

		if (getClient().getState() != GameClientState.IN_GAME) {
			// should always be null
			// but if not then this is repeated packet and nothing should be
			// done here
			if (getClient().getActiveChar() != null)
				return;
			// load up character from disk 临时屏蔽这段
			FuzePcInstance cha = getClient().loadCharFromDisk(_charSlot);

			if (cha == null) {
				_log.error("Character could not be loaded (slot:" + _charSlot + ")  " + getClient(), Config.SERVER_ID);
				sendPacket(ActionFailed.STATIC_PACKET);
				return;
			}

			if (cha.getAccessLevel().getLevel() < 0) {
				cha.closeNetConnection();
				return;
			}

			if (!Config.CACHE_CHAR_NAMES)
				CharNameTable.getInstance().addName(cha);

			cha.setClient(getClient());
			getClient().setActiveChar(cha);
			getClient().setState(GameClientState.IN_GAME);

			activeChar = getClient().getActiveChar();

			// 是否启用恢复到副本功能
			if (Config.RESTORE_PLAYER_INSTANCE)
				activeChar.setInstanceId(InstanceManager.getInstance().getPlayerInstance(activeChar.getObjectId()));
			else {
				int instanceId = InstanceManager.getInstance().getPlayerInstance(activeChar.getObjectId());
				if (instanceId > 0)
					InstanceManager.getInstance().getInstance(instanceId).removePlayer(activeChar.getObjectId());
			}

			// Apply special GM properties to the GM when entering
			if (activeChar.isGM()) {
				if (Config.GM_STARTUP_INVULNERABLE && AdminCommandAccessRights.getInstance().hasAccess("admin_invul", activeChar.getAccessLevel()))
					activeChar.setIsInvul(true);

				if (Config.GM_STARTUP_INVISIBLE && AdminCommandAccessRights.getInstance().hasAccess("admin_invisible", activeChar.getAccessLevel()))
					activeChar.getAppearance().setInvisible();

				if (Config.GM_STARTUP_SILENCE && AdminCommandAccessRights.getInstance().hasAccess("admin_silence", activeChar.getAccessLevel()))
					activeChar.setMessageRefusal(true);

				if (Config.GM_STARTUP_AUTO_LIST && AdminCommandAccessRights.getInstance().hasAccess("admin_gmliston", activeChar.getAccessLevel()))
					GmListTable.getInstance().addGm(activeChar, false);
				else
					GmListTable.getInstance().addGm(activeChar, true);
			}

			//如果HP小于1设置为死亡状态,设置等待复活
			if (activeChar.getCurrentHp() < 1) {
				activeChar.setIsDead(true);
				activeChar.setIsPendingRevive(true);
				Scene s = activeChar.getScene();//获得死亡时的所在场景
				switch (activeChar.getRace()) {
				case HUMAN:
					activeChar.getPosition().setScene(FuzeWorld.getInstance().getScene(s.getHumanReviveScene()));
					activeChar.getPosition().setScenePosition(s.getHumanReviveX(), s.getHumanReviveY());
					break;
				case ELF:
					activeChar.getPosition().setScene(FuzeWorld.getInstance().getScene(s.getELFReviveScene()));
					activeChar.getPosition().setScenePosition(s.getELFReviveX(), s.getELFReviveY());
					break;
				}
			}
			boolean showClanNotice = false;

			// Clan related checks are here
			// if (activeChar.getClan() != null) {
			// activeChar.sendPacket(new PledgeSkillList(activeChar.getClan()));
			//
			// notifyClanMembers(activeChar);
			//
			// notifySponsorOrApprentice(activeChar);
			//
			// sendPacket(new PledgeShowMemberListAll(activeChar.getClan(),
			// activeChar));
			// sendPacket(new PledgeStatusChanged(activeChar.getClan()));
			//
			// showClanNotice = activeChar.getClan().isNoticeEnabled();
			// }

			activeChar.sendPacket(new UserBaseInfo(activeChar));
			activeChar.sendPacket(new ReponseChatSwitches()); //-- 下发给客户端聊天开关设置信息
			activeChar.sendPacket(new PkModelPacket(activeChar));
			// Send Item List
			// sendPacket(new ItemList(activeChar, false));

			// Send GG check
			// activeChar.queryGameGuard();

			// 发送快捷方式
			ShortCutRegister scr = new ShortCutRegister();
			for (L2ShortCut sc : activeChar.getAllShortCuts())
				scr.addShortCut(sc);
			sendPacket(scr);

			// 任务部分
			// Quest.playerEnter(activeChar);
			// loadTutorial(activeChar);
			// for (Quest quest :
			// QuestManager.getInstance().getAllManagedScripts()) {
			// if (quest != null && quest.getOnEnterWorld())
			// quest.notifyEnterWorld(activeChar);
			// }

			if (Config.PLAYER_SPAWN_PROTECTION > 0)
				activeChar.setProtection(true);

			// if (L2Event.active &&
			// L2Event.connectionLossData.containsKey(activeChar.getName()) &&
			// L2Event.isOnEvent(activeChar))
			// L2Event.restoreChar(activeChar);
			// else if
			// (L2Event.connectionLossData.containsKey(activeChar.getName()))
			// L2Event.restoreAndTeleChar(activeChar);

			// 结婚检查
			if (Config.L2JMOD_ALLOW_WEDDING) {
				engage(activeChar);
				notifyPartner(activeChar, activeChar.getPartnerId());
			}

			activeChar.updateEffectIcons();

			// activeChar.sendPacket(new EtcStatusUpdate(activeChar));

			// Expand Skill
			// activeChar.sendPacket(new ExStorageMaxCount(activeChar));

			sendPacket(new SystemMessage(SystemMessageId.WELCOME_TO_INNOVATION));

			// if (showClanNotice) {
			// NpcHtmlMessage notice = new NpcHtmlMessage(1);
			// notice.setFile("data/html/clanNotice.htm");
			// notice.replace("%clan_name%", activeChar.getClan().getName());
			// notice.replace("%notice_text%",
			// activeChar.getClan().getNotice().replaceAll("\r\n", "<br>"));
			// sendPacket(notice);
			// } else if (Config.SERVER_NEWS) {
			// String serverNews =
			// HtmCache.getInstance().getHtm("data/html/servnews.htm");
			// if (serverNews != null)
			// sendPacket(new NpcHtmlMessage(1, serverNews));
			// }

			// activeChar.onPlayerEnter();

			// 发送技能冷却数据
			for (TimeStamp ts : activeChar.getSkillCoolList().getSkillTimeStamps().values()) {
				if (ts != null) {
					sendPacket(new MagicSkillUse(ts.getSkill(), ts.getItemId(), (int) ts.getRemaining(), 0, (int) activeChar.getSkillCoolList().getSkillCatCoolTimeById(ts.getSkill())));

				}
			}

			for (L2ItemInstance i : activeChar.getInventory().getItems()) {
				if (i.isTimeLimitedItem()) {
					i.scheduleLifeTimeTask();
				}
			}

			// if (activeChar.getClanJoinExpiryTime() >
			// System.currentTimeMillis())
			// activeChar.sendPacket(new
			// SystemMessage(SystemMessageId.CLAN_MEMBERSHIP_TERMINATED));

			// RegionBBSManager.getInstance().changeCommunityBoard();

			// L2ClassMasterInstance.showQuestionMark(activeChar);

			Engine.getInstance().addTask(this);
		} else {
			activeChar = getClient().getActiveChar();
			if (activeChar == null)
				return;

			if (!activeChar.getClient().isDetached()) {
				int x = activeChar.getX();
				int y = activeChar.getY();
				int sceneId = activeChar.getScene().get_id();
				// 把对象加入世界对象管理器
				FuzeWorld.getInstance().enterWorld(activeChar);
				// 检测距上一次离线是否在组队情况下
				L2PartyManager.getInstance().checkTimeOut(activeChar);
				// 发送场景跳转数据，通知场景上其他所有玩家
				activeChar.teleToLocation(sceneId, x, y);

				activeChar.getFriendInstance().sendLoginMessage();
				Announcements.getInstance().showAnnouncements(activeChar);//公告
				ConsignmentManager.reTakeMoney(activeChar);//取回寄售系统金钱

				//把背包内的道具进入世界
				activeChar.getInventory().spawnMe();

				//把仓库内的道具进入世界
				activeChar.getWarehouse().spawnMe();

				activeChar.getStatus().startRegeneration();

				activeChar.onPlayerEnter();

				_log.info("角色上线:", activeChar.getObjectId(), activeChar.getName());
			}
		}
	}

	/**
	 * @param activeChar
	 */
	private void engage(FuzePcInstance cha) {
		long _chaid = cha.getObjectId();

		for (Couple cl : CoupleManager.getInstance().getCouples()) {
			if (cl.getPlayer1Id() == _chaid || cl.getPlayer2Id() == _chaid) {
				if (cl.getMaried())
					cha.setMarried(true);

				cha.setCoupleId(cl.getId());

				if (cl.getPlayer1Id() == _chaid)
					cha.setPartnerId(cl.getPlayer2Id());
				else
					cha.setPartnerId(cl.getPlayer1Id());
			}
		}
	}

	/**
	 * @param activeChar
	 *            partnerid
	 */
	private void notifyPartner(FuzePcInstance cha, long partnerId) {
		if (cha.getPartnerId() != 0) {
			FuzePcInstance partner;
			long objId = cha.getPartnerId();

			try {
				partner = (FuzePcInstance) FuzeWorld.getInstance().findObject(cha.getPartnerId());

				if (partner != null)
					partner.sendMessage("Your Partner has logged in.");

				partner = null;
			} catch (ClassCastException cce) {
				_log.warn("Wedding Error: ID " + objId + " is now owned by a(n) " + FuzeWorld.getInstance().findObject(objId).getClass().getSimpleName());
			}
		}
	}

	/**
	 * @param activeChar
	 */
	private void notifyFriends(FuzePcInstance cha) {
		Connection con = null;

		try {
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement;
			statement = con.prepareStatement("SELECT friend_name FROM character_friends WHERE charId=?");
			statement.setLong(1, cha.getObjectId());
			ResultSet rset = statement.executeQuery();

			FuzePcInstance friend;
			String friendName;

			SystemMessage sm = new SystemMessage(SystemMessageId.FRIEND_S1_HAS_LOGGED_IN);
			sm.addString(cha.getName());

			while (rset.next()) {
				friendName = rset.getString("friend_name");

				// friend = WorldManager.getInstance().getPlayer(friendName);
				//
				// if (friend != null) //friend logged in.
				// {
				// friend.sendPacket(new FriendList(friend));
				// friend.sendPacket(sm);
				// }
			}
			sm = null;

			rset.close();
			statement.close();
		} catch (Exception e) {
			_log.error("Error restoring friend data.", e);
		} finally {
			try {
				con.close();
			} catch (Exception e) {
			}
		}
	}

	/**
	 * @param activeChar
	 */
	private void notifyClanMembers(FuzePcInstance activeChar) {
		// L2Clan clan = activeChar.getClan();
		//
		// // This null check may not be needed anymore since notifyClanMembers
		// is called from within a null check already. Please remove if we're
		// certain it's ok to do so.
		// if (clan != null) {
		// clan.getClanMember(activeChar.getObjectId()).setPlayerInstance(activeChar);
		// SystemMessage msg = new
		// SystemMessage(SystemMessageId.CLAN_MEMBER_S1_LOGGED_IN);
		// msg.addString(activeChar.getName());
		// clan.broadcastToOtherOnlineMembers(msg, activeChar);
		// msg = null;
		// clan.broadcastToOtherOnlineMembers(new
		// PledgeShowMemberListUpdate(activeChar), activeChar);
		// }
	}

	/**
	 * @param activeChar
	 */
	private void notifySponsorOrApprentice(FuzePcInstance activeChar) {
		if (activeChar.getSponsor() != 0) {
			FuzePcInstance sponsor = (FuzePcInstance) FuzeWorld.getInstance().findObject(activeChar.getSponsor());

			if (sponsor != null) {
				SystemMessage msg = new SystemMessage(SystemMessageId.YOUR_APPRENTICE_S1_HAS_LOGGED_IN);
				msg.addString(activeChar.getName());
				sponsor.sendPacket(msg);
			}
		} else if (activeChar.getApprentice() != 0) {
			FuzePcInstance apprentice = (FuzePcInstance) FuzeWorld.getInstance().findObject(activeChar.getApprentice());

			if (apprentice != null) {
				SystemMessage msg = new SystemMessage(SystemMessageId.YOUR_SPONSOR_C1_HAS_LOGGED_IN);
				msg.addString(activeChar.getName());
				apprentice.sendPacket(msg);
			}
		}
	}

	/**
	 * @param string
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private String getText(String string) {
		try {
			String result = new String(Base64.decode(string), "UTF-8");
			return result;
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}

	private void loadTutorial(FuzePcInstance player) {
		QuestState qs = player.getQuestState("255_Tutorial");

		if (qs != null)
			qs.getQuest().notifyEvent("UC", null, player);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see labox.innovation.gameserver.clientpackets.ClientBasePacket#getType()
	 */
	@Override
	public String getType() {
		return _C__03_ENTERWORLD;
	}
}
